package com.lagou.rpc.common;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 请求耗时统计,全局唯一
 */
public class RequestMetrics {
    /**
     * 记录服务器请求响应时间
     */
    private static final ConcurrentHashMap<String, String> TIME_COST_MAP = new ConcurrentHashMap<>();
    /**
     * 存储请求id和服务器耗时对象
     */
    private static final ConcurrentHashMap<String, Metric> REQUEST_METRIC_MAP = new ConcurrentHashMap<>();

    private static RequestMetrics requestMetrics;

    private RequestMetrics() {
    }

    public static RequestMetrics getInstance() {
        if (requestMetrics == null) {
            synchronized (RequestMetrics.class) {
                requestMetrics = new RequestMetrics();
            }
        }
        return requestMetrics;
    }

    public ConcurrentHashMap<String, String> getTimeMap() {
        return TIME_COST_MAP;
    }

    /**
     * 存放临时耗时对象
     *
     * @param ip
     * @param port
     * @param requestId
     */
    public void put(String ip, int port, String requestId) {
        REQUEST_METRIC_MAP.put(requestId, new Metric(ip, port, System.currentTimeMillis(), null));
    }

    /**
     * 计算请求时间并放入到耗时记录TIME_COST_MAP中
     */
    public void calculate(String requestId) {
        Metric metric = REQUEST_METRIC_MAP.get(requestId);
        Long costTime = System.currentTimeMillis() - metric.getStart();
        TIME_COST_MAP.put(metric.getIp() + ":" + metric.getPort(), metric.getStart() + "#" + costTime);
        REQUEST_METRIC_MAP.remove(requestId);
    }

    /**
     * 服务端节点增加时添加节点耗时记录
     *
     * @param ip
     * @param port
     */
    public void addNode(String ip, int port) {
        TIME_COST_MAP.put(ip + ":" + port, System.currentTimeMillis() + "#" + 0L);
    }

    /**
     * 服务端移除时移除节点耗时记录
     *
     * @param ip
     * @param port
     */
    public void removeNode(String ip, int port) {
        TIME_COST_MAP.remove(ip + ":" + port);
    }

    public List<Metric> getAllMetrics() {
        List<Metric> list = new ArrayList();
        TIME_COST_MAP.entrySet().stream().forEach(entry -> {
            String addr = entry.getKey();
            String value = entry.getValue();
            String[] split = value.split("#");
            Long lastRequestTime = Long.parseLong(split[0]);
            Long costTime = Long.parseLong(split[1]);
            //如果距离上次请求时间超过5s则将耗时归0
            if (System.currentTimeMillis() - lastRequestTime > 5000) {
                costTime = 0L;
            }
            String[] split1 = addr.split(":");
            list.add(new Metric(split1[0], Integer.parseInt(split1[1]), null, costTime));
        });
        return list;
    }

}
